#ifndef __DALELIB_RIBBONMANAGER_H__
#define __DALELIB_RIBBONMANAGER_H__

#include <dalelib/maths.h>
#include <map>
using namespace std;
//blob

namespace dalelib
{

struct Ribbon
{
	string _name;
	v3 _colour;
	float _decay;
	float _width;
	float _thresh; // minimum distance threshold
	vector<v4> _ribbon; // x,y,z,life

	Ribbon(const string _Name,const v3 _Colour,const float _Decay,const float _Width,const float _Thresh)
		: _name(_Name)
		, _colour(_Colour)
		, _decay(_Decay)
		, _width(_Width)
		, _thresh(_Thresh)
	{ }

	void setColour(const v3 _Colour) { _colour = _Colour; }

	void clear() { _ribbon.clear(); }

	void addPoint(const v4 _Point)
	{
		if(_ribbon.empty())
		{
			_ribbon.push_back(_Point);
		}
		else
		{
			if( (_Point.xyz()-_ribbon[_ribbon.size()-1].xyz()).len()>_thresh )
			{
				_ribbon.push_back(_Point);
			}
		}

	}
	void addPoint(const v3 _Pos,const float _Life=1.f)
	{
		addPoint(v4(_Pos[0],_Pos[1],_Pos[2],_Life));
	}
	vector<v4>& getPoints() { return _ribbon; }

	void draw()
	{
		glLineWidth(_width);
		glBegin(GL_LINE_STRIP);
		for(unsigned int i=0; i<_ribbon.size(); ++i)
		{
			glColor4f( _colour[0], _colour[1], _colour[2], _ribbon[i].w() );
			glVertex3fv(_ribbon[i].xyz().ptr());
			_ribbon[i].w() -= _decay;
		}
		glEnd();

		glPointSize(_width+2);
		glBegin(GL_POINTS);
		for(unsigned int i=0; i<_ribbon.size(); i+=10)
		{
			glColor4f( _colour[0], _colour[1], _colour[2], _ribbon[i].w() );
			glVertex3fv(_ribbon[i].xyz().ptr());
		}
		glEnd();

		if(_ribbon.size()) if(_ribbon[0].w()<0.f) _ribbon.erase(_ribbon.begin());
	}
};


//*********************************************************
class RibbonManager
{
private:

	typedef vector<Ribbon*> RibbonList;
	RibbonList _ribbon_list;
	typedef map<string,Ribbon*> RibbonMap;
	RibbonMap _ribbon_map;

public:
	RibbonManager() {}

	virtual ~RibbonManager()
	{
		for(unsigned int i=0; i<_ribbon_list.size(); ++i)
		{
			delete _ribbon_list[i];
		}
	}

	Ribbon* getRibbon(const int _Index) { return _ribbon_list[_Index]; }

	Ribbon* getRibbon(const string _Name) { return _ribbon_map[_Name]; }

	void addRibbon(const string _Name,const v3 _Colour=v3(1,1,1),const float _Decay=0.1f,const float _Width=1.f,const float _Thresh=0.1f)
	{
		Ribbon* r = new Ribbon(_Name,_Colour,_Decay,_Width,_Thresh);
		_ribbon_list.push_back(r);
		_ribbon_map[_Name] = r;
	}

	void draw()
	{
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
		glDisable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		for(unsigned int i=0; i<_ribbon_list.size(); ++i)
		{
			_ribbon_list[i]->draw();
		}
		glDisable(GL_BLEND);
		glColor4f(1,1,1,1);
	}

};

} // namespace dalelib

#endif // __DALELIB_RIBBONMANAGER_H__
